﻿using System.Threading;
using System.Web;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Dialect;
using System.IO;
using System;
using System.Data;

namespace LightWeb.Respository
{
    public class NH3SessionFactory
    {
        public void InitConfig()
        {
            var cfg = new Configuration();
            cfg.SessionFactory()
                .Named("NHibernate")
                .GenerateStatistics()
                .Using(EntityMode.Poco)
                .ParsingHqlThrough<NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory>()
                .Integrate
                .Using<SQLiteDialect>()
                .Connected
                .ByAppConfing("BlogServicesDb");


        }

    }
    public class OurTransactionScope : IDisposable
    {
        bool commited = false;
        bool rollbacked = false;
        public OurTransactionScope()
        {
            DataContext.Current.BeginTransaction();
        }

        public void Complete()
        {
            try
            {
                DataContext.Current.Commit();
                commited = true;
            }
            catch (Exception)
            {
                try
                {
                    DataContext.Current.RollBack();
                    rollbacked = true;
                }
                catch (Exception)
                {
                    throw;
                }
                throw;
            }
        }

        #region IDisposable Members

        public void Dispose()
        {
            if (!commited && !rollbacked)
                try
                {
                    DataContext.Current.RollBack();
                }
                catch (Exception)
                {
                    throw;
                }
        }

        #endregion
    }
    public class SessionFactory
    {
        private static string _sessionStoreKey = "SESSION_STORE_KEY";
        public static Configuration _configuration { get; private set; }
        private static ISessionFactory _sessionFactory;
        public static void InitialConfiguration(Configuration config)
        {
            _configuration = config;
        }

        public static ISession GetSessionInstance()
        {
            return GetSessionInstance(string.Empty);
        }

        public static ISession GetSessionInstance(string fileName)
        {
            var session = GetSessionFromCache();
            if (session == null)
            {
                Initial(fileName);
                session = _sessionFactory.OpenSession();
                CacheSession(session);
            }
            return GetSessionFromCache();
        }

        internal static void Initial(string fileName)
        {
            if (_sessionFactory == null)
            {
                if (_configuration == null)
                {
                    _configuration = new Configuration();
                    if (!string.IsNullOrEmpty(fileName) && File.Exists(fileName))
                        _configuration.Configure(fileName);
                    else
                        _configuration.Configure();
                    _sessionFactory = _configuration.BuildSessionFactory();
                }
            }
        }

        private static void CacheSession(ISession session)
        {
            ContextStorage.Save(_sessionStoreKey, session);
        }

        private static ISession GetSessionFromCache()
        {
            return ContextStorage.Load<ISession>(_sessionStoreKey);
        }
    }
   
    internal class ContextStorage
    {
        internal static void Save<T>(string key, T value)
        {
            if (HttpContext.Current != null)
            {
                if (HttpContext.Current.Items.Contains(key))
                {
                    HttpContext.Current.Items.Remove(key);
                }
                HttpContext.Current.Items.Add(key, value);
            }
            else
            {
                Thread.SetData(Thread.GetNamedDataSlot(key), value);
            }
        }

        internal static T Load<T>(string key)
        {
            if (HttpContext.Current != null)
            {
                return (T)HttpContext.Current.Items[key];
            }
            else
            {
                return (T)Thread.GetData(Thread.GetNamedDataSlot(key));
            }
        }
    }
}
